﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Notifications;
using Avalonia.Platform.Storage;
using Decrypt.Models;
using Decrypt.Services.IServices;
using Decrypt.Views;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace Decrypt.ViewModels;

/// <summary>
/// 主页ViewModel
/// </summary>
public class MainPageViewModel : ViewModelBase {
    // ******** 构造函数

    #region 构造函数

    /// <summary>
    /// 日志服务
    /// </summary>
    private ILogService _logService;

    /// <summary>
    /// 解密服务
    /// </summary>
    private IDecryptService _decryptService;


    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="logService">日志服务</param>
    /// <param name="decryptService">解密服务</param>
    public MainPageViewModel(ILogService logService,
        IDecryptService decryptService) {
        _logService = logService;
        _decryptService = decryptService;
    }

    #endregion

    // ******** 绑定属性

    /// <summary>
    /// 选择的文件路径
    /// </summary>
    public string SelectedFilePath {
        get => _selectedFilePath;
        set => Set(nameof(SelectedFilePath), ref _selectedFilePath, value);
    }

    /// <summary>
    /// 选择的文件路径
    /// </summary>
    private string _selectedFilePath;

    /// <summary>
    /// 选择的文件夹路径
    /// </summary>
    public string SelectedDirectory {
        get => _selectedDirectory;
        set => Set(nameof(SelectedDirectory), ref _selectedDirectory, value);
    }

    /// <summary>
    /// 选择的文件夹路径
    /// </summary>
    private string _selectedDirectory;

    // ******** 绑定命令

    #region 页面显示命令

    /// <summary>
    /// 页面显示命令
    /// </summary>
    private RelayCommand _pageAppearingCommand;

    /// <summary>
    /// 页面显示命令
    /// </summary>
    public RelayCommand PageAppearingCommand =>
        _pageAppearingCommand ?? (_pageAppearingCommand =
            new RelayCommand(async () => await PageAppearingCommandFunction()));

    public async Task PageAppearingCommandFunction() {
        //TODO 初始化属性数值
        _decryptService.Decrypt += DecryptServiceDecryptEventHandle;
    }

    #endregion

    #region 打开文件或目录命令

    /// <summary>
    /// 打开文件或目录命令
    /// </summary>
    private RelayCommand<string> _openFileOrDirectoryCommand;

    /// <summary>
    /// 打开文件或目录命令
    /// </summary>
    public RelayCommand<string> OpenFileOrDirectoryCommand =>
        _openFileOrDirectoryCommand ?? (_openFileOrDirectoryCommand =
            new RelayCommand<string>(async openType =>
                await OpenFileOrDirectoryCommandFunction(openType)));

    public async Task OpenFileOrDirectoryCommandFunction(string openType) {
        switch (openType) {
            //选择若干文件
            case "Files": {
                var topLevel = TopLevel.GetTopLevel(MainPage);
                var files = await topLevel!.StorageProvider.OpenFilePickerAsync(
                    new FilePickerOpenOptions {
                        Title = "选择文件", AllowMultiple = true
                    });
                if (files.Count >= 1) {
                    SelectedFilePath = string.Empty;
                    _selectedFiles.Clear();

                    var tempNames = new List<string>();
                    foreach (var file in files) {
                        _selectedFiles.Add(new EncryptedFile {
                            FilePath = file.Path.LocalPath, FileName = file.Name
                        });
                        tempNames.Add(file.Name);
                        SelectedFilePath += file.Name;
                    }

                    SelectedFilePath = string.Join(';', tempNames);
                }

                break;
            }
            //选择文件夹
            case "Directory": {
                var topLevel = TopLevel.GetTopLevel(MainPage);
                var folder =
                    await topLevel!.StorageProvider.OpenFolderPickerAsync(
                        new FolderPickerOpenOptions {
                            Title = "选择文件夹", AllowMultiple = false
                        });
                if (folder.Count == 1)
                    SelectedDirectory = folder[0].Path.LocalPath;

                break;
            }
        }
    }

    #endregion

    #region 解密命令

    /// <summary>
    /// 解密命令
    /// </summary>
    private RelayCommand<string> _decryptCommand;

    /// <summary>
    /// 解密命令
    /// </summary>
    public RelayCommand<string> DecryptCommand =>
        _decryptCommand ?? (_decryptCommand =
            new RelayCommand<string>(async decryptType =>
                await DecryptCommandFunction(decryptType)));

    public async Task DecryptCommandFunction(string decryptType) {
        switch (decryptType) {
            //解密若干文件
            case "Files": {
                if (!_selectedFiles.Any()) {
                    MainPage.ShowPopup(NotificationType.Warning, "操作提示",
                        "请先选择要解密的文件");
                    return;
                }


                foreach (var encryptedFile in _selectedFiles)
                    await _decryptService.DecryptOneAsync(
                        encryptedFile.FilePath, encryptedFile.FileName);

                break;
            }
            //解密文件夹
            case "Directory": {
                if (string.IsNullOrWhiteSpace(SelectedDirectory)) {
                    MainPage.ShowPopup(NotificationType.Warning, "操作提示",
                        "请先选择要解密的文件夹");
                    return;
                }

                await _decryptService.DecryptDirectoryAsync(SelectedDirectory);

                break;
            }
        }
    }

    #endregion

    #region 关闭命令

    /// <summary>
    /// 关闭命令
    /// </summary>
    private RelayCommand _closeCommand;

    /// <summary>
    /// 关闭命令
    /// </summary>
    public RelayCommand CloseCommand =>
        _closeCommand ?? (_closeCommand =
            new RelayCommand(async () => await CloseCommandFunction()));

    public async Task CloseCommandFunction() {
        Process.GetCurrentProcess().Kill();
    }

    #endregion

    // ******** 公开变量

    /// <summary>
    /// MainPage
    /// </summary>
    public MainPage MainPage =>
        _mainPage ?? (_mainPage =
            (Application.Current.ApplicationLifetime as
                IClassicDesktopStyleApplicationLifetime)
            .MainWindow as MainPage);

    /// <summary>
    /// MainPage
    /// </summary>
    private MainPage _mainPage;

    // ******** 私有变量

    /// <summary>
    /// 被选择的多个文件路径
    /// </summary>
    private List<EncryptedFile> _selectedFiles = new();

    // ******** 公开方法

    // ******** 私有方法

    #region 事件处理函数

    /// <summary>
    /// 解密服务解密事件处理函数
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">解密事件参数</param>
    /// <exception cref="NotImplementedException"></exception>
    private void DecryptServiceDecryptEventHandle(object? sender,
        DecryptEventArgs e) {
        if (e.DecryptSuccessful)
            MainPage.ShowPopup(NotificationType.Success, "解密结果",
                $"文件{e.FileName}解密成功!");
        else
            MainPage.ShowPopup(NotificationType.Error, "解密结果",
                $"文件{e.FileName}解密失败!");
    }

    #endregion
}